/**
 * ReportGear(2011)
 */
package net.abbp.report.view.cell.editor;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

import net.abbp.report.model.Cell;
import net.abbp.report.model.cell.style.FontStyle;
import net.abbp.report.model.cell.style.HorizentalAlignment;
import net.abbp.report.model.cell.style.Style;
import net.abbp.report.model.cell.style.background.ColorBackground;
import net.abbp.report.view.grid.Grid;

import net.abbp.core.util.StringUtils;

/**
 * 通用单元格编辑器
 * 
 * @version 1.0 2011-3-22
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since report 1.0
 */
public final class GeneralCellEditor extends AbstractCellEditor {
    private static class EditTextField extends JTextField {

        private static final long serialVersionUID = -2927543086993520920L;

        private class TextDocument extends PlainDocument {

            private static final long serialVersionUID = -7726315164363870020L;

            public TextDocument() {

            }

            @Override
            public void insertString(int offs, String string, AttributeSet attSet) throws BadLocationException {
                final String str = this.getText(0, this.getLength());
                if ((str != null) && (str.length() > EditTextField.this.getMaxLength())) {
                    Toolkit.getDefaultToolkit().beep();
                    return;
                }
                super.insertString(offs, string, attSet);
            }
        }

        /**
         * 最长字符宽度
         */
        private int maxLength;

        public EditTextField() {
            this(10000);
        }

        public EditTextField(int maxLength) {
            this.maxLength = maxLength;
            this.setDocument(new TextDocument());
        }

        public int getMaxLength() {
            return this.maxLength;
        }

        public void setMaxLength(int maxLength) {
            this.maxLength = maxLength;
        }
    }

    /**
     * 单元格对象
     */
    Grid grid;
    EditTextField textField = new EditTextField();
    String oldValue = "";
    private KeyListener textKeyListener = new KeyListener() {

        public void keyTyped(KeyEvent keyEvent) {
            ajustTextFieldSize();
        }

        public void keyPressed(KeyEvent evt) {
            int keyCode = evt.getKeyCode();
            if (keyCode == KeyEvent.VK_ESCAPE) {
                textField.setText(oldValue);
                evt.consume();
            } else {
                if ((keyCode != KeyEvent.VK_ENTER) && (keyCode != KeyEvent.VK_TAB) && (keyCode != KeyEvent.VK_UP)
                        && (keyCode != KeyEvent.VK_DOWN)) {
                    return;
                }

                GeneralCellEditor.this.grid.requestFocus();
                GeneralCellEditor.this.grid.dispatchEvent(evt);
            }
        }

        public void keyReleased(KeyEvent evt) {
        }
    };

    public GeneralCellEditor() {
        this.textField.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 1));
        this.textField.addKeyListener(this.textKeyListener);
        this.textField.addFocusListener(new FocusAdapter() {

            @Override
            public void focusLost(FocusEvent evt) {
                stopCellEditing();
            }
        });
        this.textField.setFocusTraversalKeysEnabled(false);
    }

    public int getMaxLength() {
        return this.textField.getMaxLength();
    }

    public void setMaxLength(int maxLen) {
        this.textField.setMaxLength(maxLen);
    }

    public Object getCellEditorValue() {
        return this.textField.getText();
    }

    public Component getCellEditorComponent(Grid grid, Cell cell) {
        this.grid = grid;
        Object value = cell.getValue();

        if (value == null) {
            value = "";
        }

        this.oldValue = StringUtils.convertToString(value);
        this.textField.setText(this.oldValue);

        Style style = cell.getStyle();
        ajustTextStyle(grid, style, value);

        return this.textField;
    }

    protected void ajustTextStyle(JComponent component, Style style, Object obj) {
        if (style == null) {
            style = Style.DEFAULT_STYLE;
        }
        HorizentalAlignment hAlign = style.getHorizentalAlignment();
        if (hAlign == HorizentalAlignment.Left) {
            this.textField.setHorizontalAlignment(SwingConstants.LEFT);
        } else if (hAlign == HorizentalAlignment.Center) {
            this.textField.setHorizontalAlignment(SwingConstants.CENTER);
        } else if (hAlign == HorizentalAlignment.Right) {
            this.textField.setHorizontalAlignment(SwingConstants.RIGHT);
        } else {
            this.textField.setHorizontalAlignment(SwingConstants.LEFT);
        }

        FontStyle font = style.getFontStyle();
        this.textField.setFont(new Font(font.getFontName(), font.getStyle(), font.getSize()));
        this.textField.setForeground(style.getFontStyle().getForeground());
        if (style.getBackground() instanceof ColorBackground) {
            this.textField.setBackground(((ColorBackground) style.getBackground()).getColor());
        } else {
            this.textField.setBackground(Color.WHITE);
        }
    }

    void ajustTextFieldSize() {
        Dimension dim1 = this.textField.getSize();
        Dimension dim2 = this.textField.getPreferredSize();
        this.textField.setSize((int) Math.max(dim1.getWidth(), dim2.getWidth()), (int) dim1.getHeight());
    }
}
